// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat.im.util;

import com.eva.framework.utils.LoggerFactory;
import com.google.gson.Gson;
import com.x52im.rainbowchat.common.dto.cnst.UserProtocalsType;
import com.x52im.rainbowchat.http.logic.dto.GroupEntity;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rainbowchat.im.ChatServerEventListener;
import com.x52im.rainbowchat.im.ChatServerLauncher;
import com.x52im.rainbowchat.im.dto.CMDBody4AddFriendRequest;
import com.x52im.rainbowchat.im.dto.CMDBody4GroupNameChangedNotification;
import com.x52im.rainbowchat.im.dto.CMDBody4MyselfBeInvitedGroupResponse;
import com.x52im.rainbowchat.im.dto.CMDBody4ProcessFriendRequest;
import com.x52im.rainbowchat.im.dto.MsgBody4Group;
import com.x52im.rainbowchat.im.dto.MsgBody4Guest;
import com.x52im.rainbowchat.im.impl.OfflineMessageManager;
import com.x52im.rainbowchat.im.impl.UsersStatusManager;

import net.x52im.mobileimsdk.server.network.MBObserver;
import net.x52im.mobileimsdk.server.protocal.Protocal;
import net.x52im.mobileimsdk.server.protocal.ProtocalFactory;
import net.x52im.mobileimsdk.server.utils.GlobalSendHelper;

/**
 * 服务端主动发出的或收到的消息处理辅助类（即消息发送模式为C2S或S2C的情况）.
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public class MessageHelper
{
	/**
	 * 由服务端主动发起的一条消息。
	 * 
	 * @param to_user_id
	 * @param message
	 * @param QoS
	 * @param typeu
	 * @return
	 * @throws Exception
	 */
	public static void sendMessage(String to_user_id, String message, boolean QoS, int typeu
			, SendResultObserver sendResultObserver) throws Exception
	{
		MessageHelper.sendMessage(to_user_id, message, QoS, null, typeu, sendResultObserver);
	}
	
	/**
	 * 由服务端主动发起的一条消息。
	 * 
	 * @param to_user_id
	 * @param message
	 * @param QoS
	 * @param fingerPrint 当本参数为null时，将自动生成消息指纹码，否则使用参数指定的指纹码
	 * @param typeu
	 * @param sendResultObserver 指令发送结果观察者（因为通信底层netty是异步通知数据发送结果的）
	 * @return
	 * @throws Exception
	 * @see SendResultObserver
	 */
	public static void sendMessage(String to_user_id, String message, boolean QoS, String fingerPrint, int typeu
			, final SendResultObserver sendResultObserver) throws Exception
	{
//		boolean code = false;
//		Protocal p = ProtocalFactory.createCommonData(message, "0", to_user_id, QoS, fingerPrint, typeu);
//		if(message != null && message.length()>0)
//		{
//			// @since 4.5 以前的版本：不支持与Web端im的通信
////			code = LocalSendHelper.sendData(to_user_id, message, QoS, typeu);
//			// @since 4.5 及以后版本：可支持与Web端im的通信
//			code = GlobalSendHelper.sendDataS2C(ChatServerLauncher.getInstance().getServerCoreHandler().getBridgeProcessor(), p);
//		}
//		else
//			LoggerFactory.getLog().error("[RainbowChat]message为null或length<=0，请检查参数.");
//		return new SendResult(code, p);

		final Protocal p = ProtocalFactory.createCommonData(message, "0", to_user_id, QoS, fingerPrint, typeu);
		if(message != null && message.length()>0)
		{
			// netty是异步通知数据发送结果的
			MBObserver resultObserver = new MBObserver(){
				@Override
				public void update(boolean sucess, Object extraObj) {
					if(sendResultObserver != null)
						sendResultObserver.update(sucess, p);
				}
			};
			
			GlobalSendHelper.sendDataS2C(ChatServerLauncher.getInstance().getServerCoreHandler().getBridgeProcessor(), p, resultObserver);
		}
		else
		{
			LoggerFactory.getLog().error("[RainbowChat]message为null或length<=0，请检查参数.");
			
			if(sendResultObserver != null)
				sendResultObserver.update(false, p);
		}
	}
	
	// 上线消息是由服务端发出的，所以from_user_id==0（QoS==false主要用于发送上下线通知时，
	// 否则极端情况下重传的上线通知会后于下线通知，会搞乱上下线的通知罗辑）
	public static void sendOnlineMessage(String to_user_id, String user_id, SendResultObserver sendResultObserver) throws Exception
	{
		// 用户上线通知的格式是：上线用户uid”
		// ，形如："400005"
		sendMessage(to_user_id, user_id, false, UserProtocalsType.MT01_OF_ONLINE_NOTIVICATION, sendResultObserver);
	}
	
	// 下线消息是由服务端发出的，所以from_user_id==0（QoS==false主要用于发送上下线通知时，
	// 否则极端情况下重传的上线通知会后于下线通知，会搞乱上下线的通知罗辑）
	public static void sendOfflineMessage(String to_user_id, String userUid, SendResultObserver sendResultObserver) throws Exception
	{
		// 用户下线通知的格式是：“下线用户uid”
		// ，形如："400005"
		sendMessage(to_user_id, userUid, false, UserProtocalsType.MT02_OF_OFFLINE_NOTIVICATION, sendResultObserver);
	}
	
	//------------------------------------------------------------------------------- 加好友请求处理相关 S
	/**
	 * 由服务端反馈给加好友发起人的错误信息头(出错的可能是：该好友
	 * 已经存在于我的好友列表中、插入好友请求到db中时出错等)。
	 * 
	 * @param to_user_id
	 * @param errorMessage
	 * @return
	 * @throws Exception
	 */
	// 此消息由服务端主动发起，所以from_user_id==0
	public static void sendAddFriendRequestResponse_for$error_server$to$aMessage(
			String to_user_id, String errorMessage, SendResultObserver sendResultObserver) throws Exception
	{
		sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
				, errorMessage, true, UserProtocalsType.MT06_OF_ADD_FRIEND_REQUEST_RESPONSE$FOR$ERROR_SERVER$TO$A, sendResultObserver);
	}
	
	/**
	 * 解析用户发起添加好友的请求消息（添加好友请求处理：第2/3环节）.
	 * 
	 * @param originalMsg
	 * @return 客户端A发过来的加好友请求元数据封装对象
	 */
	public static CMDBody4AddFriendRequest pareseAddFriendRequestMessage(String originalMsg)
	{
		// 加好友请求原数据（客户端A发过来的）
		CMDBody4AddFriendRequest arm = new Gson().fromJson(
				originalMsg, CMDBody4AddFriendRequest.class);
		return arm;
	}
	
	/**
	 * 由服务端转发的加好友请求消息给在线目标用户（离线用户是不需要的哦）.
	 * 
	 * @param to_user_id 要发送到的目标客户user_id
	 * @return
	 */
	public static void sendAddFriendRequestInfo_server$to$bMessage(
			String to_user_id, RosterElementEntity srcUserInfo, SendResultObserver sendResultObserver) throws Exception
	{
		String srcUserInfoStr = new Gson().toJson(srcUserInfo);
		sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
				, srcUserInfoStr, true, UserProtocalsType.MT07_OF_ADD_FRIEND_REQUEST_INFO_SERVER$TO$B, sendResultObserver);
	}
	
	/**
	 * 解析用户B发起的处理被添加好友的请求消息：处理动作——【同意】.
	 * 
	 * @param originalMsg
	 * @return 客户端B发过来的加好友请求元数据封装对象
	 */
	public static CMDBody4ProcessFriendRequest pareseProcessAdd$Friend$Req_B$To$Server_AGREEMessage(String originalMsg)
	{
		// 加好友请求原数据（客户端A发过来的）
		CMDBody4ProcessFriendRequest arm = new Gson().fromJson(originalMsg, CMDBody4ProcessFriendRequest.class);
		return arm;
	}
	/**
	 * 解析用户B发起的处理被添加好友的请求消息：处理动作——【拒绝】.
	 * 
	 * @param originalMsg
	 * @return 客户端B发过来的加好友请求元数据封装对象
	 */
	public static CMDBody4ProcessFriendRequest pareseProcessAdd$Friend$Req_B$To$Server_REJECTMessage(String originalMsg)
	{
		// 加好友请求原数据（客户端A发过来的）
		CMDBody4ProcessFriendRequest arm = new Gson().fromJson(originalMsg, CMDBody4ProcessFriendRequest.class);
		return arm;
	}
	
	/**
	 * 新好友已成功被添加后，由服务端把好友信息实时反馈给客户端（
	 * 此场景是被请求用户同意了加好友的请求时，由服务端把双 方的好友信息及时交给对方（如果双方有人在线的话））.
	 * 
	 * @param to_user_id 要发送到的目标客户user_id
	 * @return
	 */
	// 此消息由服务端主动发起，所以from_user_id==0
	public static void sendProcessAdd$Friend$Req_friend$Info$Server$To$ClientMessage(
			String to_user_id, RosterElementEntity userInfo, SendResultObserver sendResultObserver) throws Exception
	{
		String userInfoStr = new Gson().toJson(userInfo);
		sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
				, userInfoStr, true, UserProtocalsType.MT10_OF_PROCESS_ADD$FRIEND$REQ_FRIEND$INFO$SERVER$TO$CLIENT, sendResultObserver);
	}
	
	/**
	 * 由服务端反馈给B处理加好友请求处理时的错误信息(出错的可能是：B在提交同意A的加好友请求时出错了等)。
	 * 
	 * @param to_user_id
	 * @param errorMessage
	 * @return
	 * @throws Exception
	 */
	// 此消息由服务端主动发起，所以from_user_id==0
	public static void sendProcessAddFriendReq_response$For$Rrror_server$to$bMessage(
			String to_user_id, String errorMessage, SendResultObserver sendResultObserver) throws Exception
	{
		sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
				, errorMessage, true, UserProtocalsType.MT11_OF_PROCESS_ADD$FRIEND$REQ_RESPONSE$FOR$ERROR_SERVER$TO$B, sendResultObserver);
	}
	
	/**
	 * A的加好友请求被B拒绝后，由服务端把拒绝信息实时反馈给客户端A（以便A能实时知道加好友被拒的情况）.
	 * 
	 * <p>当然，此消息被发送的前提条件是A用户此时是在线的。
	 * 
	 * @param to_user_id 要发送到的目标客户user_id
	 * @return
	 */
	// 此消息由服务端主动发起，所以from_user_id==0
	public static void sendProcessAdd$Friend$Req_SERVER$TO$A_REJECT_RESULTMessage(
			String to_user_id, RosterElementEntity userInfo, SendResultObserver sendResultObserver) throws Exception
	{
		String userInfoStr = new Gson().toJson(userInfo);
		sendMessage(to_user_id// 当起人的user_id=0时，服务端的QoS机制才有意义哦！
				, userInfoStr, true, UserProtocalsType.MT12_OF_PROCESS_ADD$FRIEND$REQ_SERVER$TO$A_REJECT_RESULT, sendResultObserver);
		
	}
	//------------------------------------------------------------------------------- 加好友请求处理相关 E
	
	
	//------------------------------------------------------------------------------- 临时聊天消息处理相关S
	/**
	 * 陌生人聊天消息：由服务端转发给接收人B的【步骤2/2】.
	 * 
	 * <p>当然，此消息被发送的前提条件是B用户此时是在线的（否则临时聊天消息将被存储到DB中）。
	 * 
	 * @param to_user_id 要发送到的目标客户user_id
	 * @return
	 */
	// 此消息由服务端主动发起，所以from_user_id==0
	public static void sendTempChatMsg_SERVER$TO$B_Message(
			String to_user_id, MsgBody4Guest tempChatMsgDTO, String fingerPrint, SendResultObserver sendResultObserver) throws Exception
	{
		String tempChatMsgDTOStr = new Gson().toJson(tempChatMsgDTO);
		sendMessage(to_user_id// 说明：因临时消息是由客户端发给服务端（代转的），客户端的QoS机制只保证到server，所以server到b也同样需要QoS=true来保证下一段的QoS哦！
							  // QoS的设置原则是：由谁发起的，就由谁启用QoS机制，否则会搞乱消息的转发逻辑哦
				, tempChatMsgDTOStr, true, fingerPrint, UserProtocalsType.MT43_OF_TEMP$CHAT$MSG_SERVER$TO$B, sendResultObserver);
		
	}
	/**
	 * 解析临时聊天消息：由发送人A发给服务端【步骤1/2】.
	 * 
	 * @param originalMsg
	 * @return 客户端A发过来的临时聊天消息：由发送人A发给服务端【步骤1/2】元数据封装对象
	 */
	public static MsgBody4Guest pareseTempChatMsg_A$TO$SERVER_Message(String originalMsg)
	{
		// 元数据（客户端A发过来的）
		MsgBody4Guest tcmd = new Gson().fromJson(originalMsg, MsgBody4Guest.class);
		return tcmd;
	}
	//------------------------------------------------------------------------------- 临时聊天消息处理相关 E
	
	//------------------------------------------------------------------------------- 群聊聊天消息处理相关S
	/**
	 * 群聊/世界频道聊天消息：由服务端转发给接收人B的【步骤2/2】.
	 * 
	 * <p>当然，此消息被发送的前提条件是B用户此时是在线的（否则BBS聊天消息将不会被发送给此人哦（会自动丢弃））。
	 * 
	 * @param to_user_id 要发送到的目标客户user_id
	 * @return
	 */
	// 此消息由服务端主动发起，所以from_user_id==0，但此参数目前对于接收方而言没有用处，以后可能会用上
	public static void sendGroupChatMsg_SERVER$TO$B_Message(
			String to_user_id, MsgBody4Group groupChatMsgDTO, SendResultObserver sendResultObserver) throws Exception
	{
		String groupChatMsgDTOStr = new Gson().toJson(groupChatMsgDTO);
		sendMessage(to_user_id
				, groupChatMsgDTOStr
				// 如需追求群发消息最大可能的性能，可设置QoS为false哦
				, true//false
				, UserProtocalsType.MT45_OF_GROUP$CHAT$MSG_SERVER$TO$B, sendResultObserver);
		
	}
	/**
	 * 解析群聊/世界频道聊天消息：由发送人A发给服务端【步骤1/2】.
	 * 
	 * @param originalMsg
	 * @return 客户端A发过来的BBS/群组聊天消息：由发送人A发给服务端【步骤1/2】元数据封装对象
	 */
	public static MsgBody4Group pareseGroupChatMsg_A$TO$SERVER_Message(String originalMsg)
	{
		// 元数据（客户端A发过来的）
		MsgBody4Group tcmd = new Gson().fromJson(originalMsg, MsgBody4Group.class);
		return tcmd;
	}
	
	/**
	 * 群聊系统指令：“我”加群成功后通知“我”（即通知被加群者）（由Server发出）。
	 * <p>
	 * “我”可能是在创建群或群建好后邀请进入的.
	 */
	public static void sendGroupSysCMD4MyselfBeInvited(String toUid
			, String newJoinUid
			, String inviteBeUid, String inviteBeNickName
			, GroupEntity groupInfo
			) throws Exception
	{
		String offlineContent = "\""+inviteBeNickName+"\"邀请你加入了群聊";
		
		// 准备好要发送的数据内容
		CMDBody4MyselfBeInvitedGroupResponse cmdBody = CMDBody4MyselfBeInvitedGroupResponse.copyFrom(groupInfo);
		cmdBody.setInviteBeUid(inviteBeUid);
		cmdBody.setInitveBeNickName(inviteBeNickName);
//		cmdBody.setNewJoinUid(newJoinUid);
//		cmdBody.setNewJoinNickName(newJoinNickName);
		
		MessageHelper.sendGroupSysCMD(UserProtocalsType.MT46_OF_GROUP$SYSCMD_MYSELF$BE$INVITE_FROM$SERVER
				, "群聊CMD-通知新加者", toUid, new Gson().toJson(cmdBody)
				, groupInfo.getG_id()
//				, groupInfo.getG_name()
				, offlineContent);
	}
	
	/**
	 * 群聊系统指令：发出一条通用的系统信息给指定群员（由Server发出）。
	 */
	public static void sendGroupSysCMD4CommonInfo(String toUid
			, String systemInfo, String gid
//			, String gname
			) throws Exception
	{
//		String notificationContent = "\""+inviteBeNickName+"\"邀请\""+newJoinNickName+"\"加入了群聊";
		MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, systemInfo);
		MessageHelper.sendGroupSysCMD(UserProtocalsType.MT47_OF_GROUP$SYSCMD_COMMON$INFO_FROM$SERVER
				, "群聊CMD-通用通知", toUid, new Gson().toJson(body)
				, gid
//				, gname
				, systemInfo);
	}
	
	/**
	 * 群聊系统指令：发出一条群已被解散通知（由Server发出，除解散者外的所有人接收） 。
	 */
	public static void sendGroupSysCMD4Dismissed(String toUid, String dismissUserName
			, String gid
//			, String gname
			) throws Exception
	{
		String notificationContent = "本群已被\""+dismissUserName+"\"解散";
		MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, notificationContent);
		MessageHelper.sendGroupSysCMD(UserProtocalsType.MT48_OF_GROUP$SYSCMD_DISMISSED_FROM$SERVER
				, "群聊CMD-解散通知", toUid, new Gson().toJson(body)
				, gid
//				, gname
				, notificationContent);
	}
	
	/**
	 * 群聊系统指令：发出一条"你"被踢出群聊（由Server发出，被踢者接收）。
	 */
	public static void sendGroupSysCMD4YouBeRemoved(String toUid, String ownerNickname
			, String gid
//			, String gname
			) throws Exception
	{
		String notificationContent = "你已被\""+ownerNickname+"\"移出本群";
		MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, notificationContent);
		MessageHelper.sendGroupSysCMD(UserProtocalsType.MT49_OF_GROUP$SYSCMD_YOU$BE$KICKOUT_FROM$SERVER
				, "群聊CMD-你被踢通知", toUid, new Gson().toJson(body)
				, gid
//				, gname
				, notificationContent);
	}
	
	/**
	 * 群聊系统指令：发出一条"别人"主动退出或被群主踢出群聊（由Server发出，其它群员接收） 。
	 * 
	 * @param himselfQuitGroup true表示本次是该人自已退群的，否则是被群主删除的
	 */
	public static void sendGroupSysCMD4SomeoneRemoved(boolean himselfQuitGroup
			, String toUid, String delOprNickname, String beRemovedNickname
			, String gid
//			, String gname
			) throws Exception
	{
		String notificationContent = null;
		
		if(himselfQuitGroup)
			notificationContent = "\""+beRemovedNickname+"\"已退出本群";
		else
			notificationContent = "\""+beRemovedNickname+"\"已被\""+delOprNickname+"\"移出本群";
			
		MsgBody4Group body = MsgBody4Group.constructGroupSystenMsgBody(gid, notificationContent);
		MessageHelper.sendGroupSysCMD(UserProtocalsType.MT50_OF_GROUP$SYSCMD_SOMEONEB$REMOVED_FROM$SERVER
				, "群聊CMD-别人退群或被踢出通知", toUid, new Gson().toJson(body)
				, gid
//				, gname
				, notificationContent);
	}
	
	/**
	 * 群聊系统指令：群名被修改的系统通知（由Server发出，所有除修改者外的群员接收）。
	 */
	public static void sendGroupSysCMD4GroupNameChanged(String toUid
			, String changedByUid, String changedByNickName
			, String newGroupName
			, String gid) throws Exception
	{
		String notificationContent = "\""+changedByNickName+"\"修改群名为\""+newGroupName+"\"";
		
		// 准备好要发送的数据内容
		CMDBody4GroupNameChangedNotification cmdBody = new CMDBody4GroupNameChangedNotification();
		cmdBody.setChangedByUid(changedByUid);
		cmdBody.setNnewGroupName(newGroupName);
		cmdBody.setNotificationContent(notificationContent);
		cmdBody.setGid(gid);
		
		MessageHelper.sendGroupSysCMD(UserProtocalsType.MT51_OF_GROUP$SYSCMD_GROUP$NAME$CHANGED_FROM$SERVER
				, "群聊CMD-群名被改", toUid, new Gson().toJson(cmdBody), gid
//				, newGroupName
				, notificationContent);
	}
	
	/**
	 * 发送群聊的系统级指令或通知（当接收者不在线时，本方法将自动进行离线处理）。
	 * 
	 * @param typeu 协议类型
	 * @param logTag 日志TAG
	 * @param toUid 发送的对象
	 * @param cmdBodyStr 要发送的协议体内容（可能是个JSON，也可能只是普通文本）
	 * @param gid 发生的群id
	 * @param gname 发生的群名称
	 * @param contentForOffline 如果接收者不在线时，要离线保存的内容
	 * @throws Exception
	 */
	private static void sendGroupSysCMD(int typeu
			, final String logTag, final String toUid, String cmdBodyStr, String gid, String contentForOffline) throws Exception
	{
		if(cmdBodyStr != null)
		{
			UsersStatusManager liveMgr = ChatServerEventListener.getInstance().getLiverUsersMgr();
			
			// 本实例中是否在线
			final boolean isOnline = liveMgr.isOnline(toUid);
			
			SendResultObserver sendResultObserver = new SendResultObserver(){
				@Override
				public void update(boolean code, Protocal p) {
					// 返回值true：对于应用层逻辑来说，无论是在线发送成功，或者是跨服桥接成功，都算是发送成功
					if(code)
					{
						LoggerFactory.getLog().info("[RBChat]【"+logTag+"】Server向"+toUid+"发送通知已成功实时发出！");
						
						// 说明：满足此条件，表示本地不在线但处于与Web互通模式的情况下，消息却发送成功，也需要进行App的push通知，
						//       因为前提是app端已不在线，进行push是合情合理的（否则桥接成功的情况下，app这边即使不在线也永远收
						//       不到app的push通知，除非web那端也要实现不在线时的app的push通知。
						// 备忘：此处的push逻辑是为了省去web那端不在线时的app push通知逻辑，日后支持全功能集群后，就不需
						//       要这个逻辑了，因为包括web集群实例在内，都将是对等的且必须支持app 的push逻辑——所以没必要以下代码。
						if(!isOnline && ChatServerLauncher.bridgeEnabled)
						{
							//## 将该条指令进行离线处理
							OfflineMessageManager.processOfflineMessage(p, true); // 注意此参数为true！ 
						}
					}
					// 返回值false：实时或桥接发送没有成功
					else
					{
						LoggerFactory.getLog().debug("[RBChat]【"+logTag+"】Server向"+toUid
								+"发送的通知无法实时或桥接发出(isOnline?"+isOnline+"，错误code="+code+")，将作离线处理【END】。");
						
						//## 将该条指令进行离线处理
						OfflineMessageManager.processOfflineMessage(p, false );
					}
				}
			};
			
			// （如果用户连在本APPP实例则直发，否则开启与web互通时将桥接发）
			// 为了提升性能，QoS建议可设为false
//			MessageHelper.sendMessage(toUid, cmdBodyStr, false, typeu, sendResultObserver);
			// 20200904：为了保证群系统通知的送达率，也启用了QoS机制哦
			MessageHelper.sendMessage(toUid, cmdBodyStr, true, typeu, sendResultObserver);
		}
		else
		{
			LoggerFactory.getLog().warn("[RBChat]【"+logTag+"】cmdBodyStr is null! (toUid="+toUid
					+", gid="+gid+", , contentForOffline="+contentForOffline+")");
		}
	}
	//------------------------------------------------------------------------------- 群聊聊天消息处理相关 E
	
	
//	/**
//	 * 消息发送结果封装类。
//	 */
//	public static class SendResult
//	{
//		// 发送结果：true表示成功发出，否则发出失败
//		private boolean code = false;
//		// 发送内容：返回本次发送的完整协议包内容（只是方便调用者后绪 使用，不是必须要用的）。
//		private Protocal p;
//		
//		public SendResult(boolean code, Protocal p)
//		{
//			this.code = code;
//			this.p = p;
//		}
//
//		public boolean isCode()
//		{
//			return code;
//		}
//
//		public Protocal getP()
//		{
//			return p;
//		}
//	}
	
	/**
	 * 消息发送结果封装类。
	 */
	public static interface SendResultObserver
	{
//		// 发送结果：true表示成功发出，否则发出失败
//		private boolean code = false;
//		// 发送内容：返回本次发送的完整协议包内容（只是方便调用者后绪 使用，不是必须要用的）。
//		private Protocal p;
//		
//		public SendResultObserver(boolean code, Protocal p)
//		{
//			this.code = code;
//			this.p = p;
//		}
//
//		public boolean isCode()
//		{
//			return code;
//		}
//
//		public Protocal getP()
//		{
//			return p;
//		}
		
		/**
		 * 发送指令完成后，通过此方法来通知异步结果的观察者。
		 * 
		 * @param code 指令发送结果：true表示成功发出，否则发出失败
		 * @param p 指令发送内容：返回本次发送的完整协议包内容（只是方便调用者后绪 使用，不是必须要用的）
		 */
		public void update(boolean code, Protocal p);
	}
}
